package com.ruoyi.monitor.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.monitor.Vo.PollutantMonthVo;
import com.ruoyi.monitor.domain.PollutantAvg;
import com.ruoyi.monitor.mapper.PollutantAvgMapper;
import com.ruoyi.monitor.service.IPolluantAvgService;
import com.ruoyi.monitor.utils.Common.Constant;
import com.ruoyi.monitor.utils.Common.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * 均值Service业务层处理
 * 
 * @author xzx
 * @date 2023-01-12
 */
@Service
public class PolluantAvgServiceImpl extends ServiceImpl<PollutantAvgMapper, PollutantAvg> implements IPolluantAvgService
{
    @Autowired
    private PollutantAvgMapper pollutantAvgMapper;

    @Override
    public PollutantAvg countAVGWeekLatest() {
        PollutantAvg avg = pollutantAvgMapper.selectOne(new LambdaQueryWrapper<PollutantAvg>()
                .orderByDesc(PollutantAvg::getCt)
                .eq(PollutantAvg::getType, 1)
                .eq(PollutantAvg::getArea, Constant.city)
                .last("limit 1")
        );
        QueryWrapper<PollutantAvg> week = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                .eq("area",Constant.city)
                .eq("type",1)
                .apply(!ObjectUtils.isEmpty(avg.getCt()),
                        //一周内的数据
                        "ct >= " + "'"+DateUtils.format(DateUtil.beginOfWeek(avg.getCt()))+"'")
                .apply(!ObjectUtils.isEmpty(avg.getCt()),
                        "ct <= " + "'"+DateUtils.format(DateUtil.endOfWeek(avg.getCt()))+"'")
                .groupBy("area", "ct") // 添加 GROUP BY 子句
                .select("avg(aqi) as aqi","area",
                        "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                        "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
        PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(week);
        pollutantAvg.setType(Constant.WEEKLY);
        DateTime beginOfWeek = DateUtil.beginOfWeek(avg.getCt());
        pollutantAvg.setStart(beginOfWeek);
        DateTime endOfWeek = DateUtil.endOfWeek(avg.getCt());

        pollutantAvg.setEnd(DateUtils.get0MIll(endOfWeek));

        return pollutantAvg;
    }

    @Override
    public PollutantAvg countAVGMonthLatest() {
        PollutantAvg avg = pollutantAvgMapper.selectOne(new LambdaQueryWrapper<PollutantAvg>()
                .eq(PollutantAvg::getType, 1)
                .eq(PollutantAvg::getArea, Constant.city)
                .orderByDesc(PollutantAvg::getCt)
                .last("limit 1")
        );
        QueryWrapper<PollutantAvg> month = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                .apply(!ObjectUtils.isEmpty(avg.getCt()),
                        //月数据
                        "ct >= " + "'"+DateUtils.format(DateUtil.beginOfMonth(avg.getCt()))+"'")
                .apply(!ObjectUtils.isEmpty(avg.getCt()),
                        "ct <= " + "'"+DateUtils.format(DateUtil.endOfMonth(avg.getCt()))+"'")
                .groupBy("area", "ct") // 添加 GROUP BY 子句
                .select("avg(aqi) as aqi","area",
                        "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                        "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
        PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(month);
        pollutantAvg.setType(Constant.MONTHLY);
        DateTime beginOfMonth = DateUtil.beginOfMonth(avg.getCt());
        pollutantAvg.setStart(beginOfMonth);
        DateTime endOfMonth = DateUtil.endOfMonth(avg.getCt());

        pollutantAvg.setEnd(DateUtils.get0MIll(endOfMonth));
        return pollutantAvg;
    }

    @Override
    public Set<PollutantAvg> CountAVGWeekAll() {
        Set<PollutantAvg> res = new TreeSet<>();
        List<PollutantAvg> pollutantAvgs = pollutantAvgMapper.selectList(new LambdaQueryWrapper<PollutantAvg>()
                .eq(PollutantAvg::getArea,Constant.city)
                .eq(PollutantAvg::getType,Constant.DAILY));
        //去除毫秒

        for (PollutantAvg avg: pollutantAvgs) {
            QueryWrapper<PollutantAvg> week = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                    .eq("area",Constant.city)
                    .eq("type",Constant.DAILY)
                    .apply(!ObjectUtils.isEmpty(avg.getCt()),
                            //一周内的数据
                            "ct >= " + "'"+DateUtils.format(DateUtil.beginOfWeek(avg.getCt()))+"'")
                    .apply(!ObjectUtils.isEmpty(avg.getCt()),
                            "ct <= " + "'"+DateUtils.format(DateUtil.endOfWeek(avg.getCt()))+"'")
                    .groupBy("area", "ct") // 添加 GROUP BY 子句
                    .select("avg(aqi) as aqi","area",
                            "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                            "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");

            PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(week);
            pollutantAvg.setType(Constant.WEEKLY);
            DateTime beginOfWeek = DateUtil.beginOfWeek(avg.getCt());
            pollutantAvg.setStart(beginOfWeek);
            DateTime endOfWeek = DateUtil.endOfWeek(avg.getCt());

            pollutantAvg.setEnd(DateUtils.get0MIll(endOfWeek));
            res.add(pollutantAvg );
        }
        System.out.println("周数据总数"+res.size());
        return res;
    }

    @Override
    public Set<PollutantAvg> CountAVGMonthAll() {
        Set<PollutantAvg> res = new TreeSet<>();
        List<PollutantAvg> pollutantAvgs = pollutantAvgMapper.selectList(new LambdaQueryWrapper<PollutantAvg>()
        .eq(PollutantAvg::getArea,Constant.city)
        .eq(PollutantAvg::getType,Constant.DAILY));
        //去除毫秒
        Date mon = null;
        for (PollutantAvg avg: pollutantAvgs) {
            if (mon == null){
                mon = avg.getCt();
                QueryWrapper<PollutantAvg> month = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                        .eq("area",Constant.city)
                        .eq("type",Constant.DAILY)
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                //月数据
                                "ct >= " + "'"+DateUtils.format(DateUtil.beginOfMonth(avg.getCt()))+"'")
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                "ct <= " + "'"+DateUtils.format(DateUtil.endOfMonth(avg.getCt()))+"'")
                        .groupBy("area", "ct") // 添加 GROUP BY 子句
                        .select("avg(aqi) as aqi","area",
                                "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                                "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
                PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(month);
                pollutantAvg.setType(Constant.MONTHLY);
                DateTime beginOfMonth = DateUtil.beginOfMonth(avg.getCt());
                pollutantAvg.setStart(beginOfMonth);
                DateTime endOfMonth = DateUtil.endOfMonth(avg.getCt());

                pollutantAvg.setEnd(DateUtils.get0MIll(endOfMonth));
                res.add(pollutantAvg );
            }else if (mon.getMonth() != avg.getCt().getMonth()){
                QueryWrapper<PollutantAvg> month = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                        .eq("area",Constant.city)
                        .eq("type",Constant.DAILY)
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                //月数据
                                "ct >= " + "'"+DateUtils.format(DateUtil.beginOfMonth(avg.getCt()))+"'")
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                "ct <= " + "'"+DateUtils.format(DateUtil.endOfMonth(avg.getCt()))+"'")
                        .groupBy("area", "ct") // 添加 GROUP BY 子句
                        .select("avg(aqi) as aqi","area",
                                "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                                "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
                PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(month);
                pollutantAvg.setType(Constant.MONTHLY);
                DateTime beginOfMonth = DateUtil.beginOfMonth(avg.getCt());
                pollutantAvg.setStart(beginOfMonth);
                DateTime endOfMonth = DateUtil.endOfMonth(avg.getCt());

                pollutantAvg.setEnd(DateUtils.get0MIll(endOfMonth));
                res.add(pollutantAvg );
            }

        }
        System.out.println("月数据总数"+res.size());
        return res;
    }

    @Override
    public Set<PollutantAvg> CountAVGYearAll() {

        Set<PollutantAvg> res = new TreeSet<>();
        List<PollutantAvg> pollutantAvgs = pollutantAvgMapper.selectList(
                new LambdaQueryWrapper<PollutantAvg>()
                .eq(PollutantAvg::getArea,Constant.city)
                .eq(PollutantAvg::getType,Constant.MONTHLY)
                .orderByDesc(PollutantAvg::getCt));
        //去除毫秒
        Date last = null;
        int a = 0;
        for (PollutantAvg avg: pollutantAvgs) {
            System.out.println(avg.getCt().getYear());
            if (last == null){
                a++;
                System.out.println("次数"+a);
                last = pollutantAvgs.get(0).getCt();
                QueryWrapper<PollutantAvg> year = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                        .eq("area",Constant.city)
                        .eq("type",Constant.MONTHLY)
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),

                                "ct >= " + "'"+DateUtils.format(DateUtil.beginOfYear(avg.getCt()))+"'")
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                "ct <= " + "'"+DateUtils.format(DateUtil.endOfYear(avg.getCt()))+"'")
                        .groupBy("area", "ct") // 添加 GROUP BY 子句
                        .select("avg(aqi) as aqi","area",
                                "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                                "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
                PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(year);
                pollutantAvg.setType(Constant.YEARLY);
                DateTime beginOfYear = DateUtil.beginOfYear(avg.getCt());
                pollutantAvg.setStart(beginOfYear);
                DateTime endOfYear = DateUtil.endOfYear(avg.getCt());

                pollutantAvg.setEnd(DateUtils.get0MIll(endOfYear));
                res.add(pollutantAvg );
            }
           else if (last.getYear()!=avg.getCt().getYear()){
                a++;
                System.out.println("次数"+a);
                last = avg.getCt();
                QueryWrapper<PollutantAvg> month = new QueryWrapper<PollutantAvg>().orderByDesc("ct")
                        .eq("area",Constant.city)
                        .eq("type",Constant.MONTHLY)
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                //月数据
                                "ct >= " + "'"+DateUtils.format(DateUtil.beginOfYear(avg.getCt()))+"'")
                        .apply(!ObjectUtils.isEmpty(avg.getCt()),
                                "ct <= " + "'"+DateUtils.format(DateUtil.endOfYear(avg.getCt()))+"'")
                        .groupBy("area", "ct") // 添加 GROUP BY 子句
                        .select("avg(aqi) as aqi","area",
                                "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                                "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
                PollutantAvg pollutantAvg = pollutantAvgMapper.selectOne(month);
                pollutantAvg.setType(Constant.YEARLY);
                DateTime beginOfYear = DateUtil.beginOfYear(avg.getCt());
                pollutantAvg.setStart(beginOfYear);
                DateTime endOfYear = DateUtil.endOfYear(avg.getCt());

                pollutantAvg.setEnd(DateUtils.get0MIll(endOfYear));
                res.add(pollutantAvg );
            }

        }
        System.out.println("年数据总数"+res.size());
        return res;
    }


    @Override
    public PollutantAvg selectDaysAVG(Date date,Integer days) {
        QueryWrapper<PollutantAvg> wrapper = new QueryWrapper<>();
        SimpleDateFormat ssm = new SimpleDateFormat("yyyy-MM-dd");
        wrapper.eq("type",Constant.DAILY)
                .eq("area",Constant.city)
                .apply(
                //**天内的数据
                "ct >= " + "'"+ssm.format(DateUtils.getPastDate(days,date))+"'")
                .apply(
                        "ct <= " + "'"+ssm.format(date)+"'")
                .groupBy("area", "ct") // 添加 GROUP BY 子句
                .select("avg(aqi) as aqi","area",
                        "ct","avg(pm25) as pm25","avg(pm10) as pm10","avg(co) as co",
                        "avg(so2) as so2","avg(no2) as no2","avg(o3) as o3");
        PollutantAvg pollutantAvgs = pollutantAvgMapper.selectOne(wrapper);
        return pollutantAvgs;
    }

    @Override
    public List<PollutantAvg> selectDaySingle(Date date, Integer days) {
        QueryWrapper<PollutantAvg> wrapper = new QueryWrapper<>();
        SimpleDateFormat ssm = new SimpleDateFormat("yyyy-MM-dd");
        if (days == 30){
            Date pastDate = DateUtils.getPastDate(5,DateUtil.beginOfMonth(new Date()));
            wrapper.eq("type",Constant.DAILY)
                    .eq("area",Constant.city)
                    .orderByAsc("ct")
                    .apply(
                            //**天内的数据
                            "ct >= " + "'"+ssm.format(DateUtil.beginOfMonth(pastDate))+"'")
                    .apply(
                            "ct <= " + "'"+ssm.format(DateUtil.endOfMonth(pastDate))+"'");
        }else if (days == 7){
            Date pastDate = DateUtils.getPastDate(5,DateUtil.beginOfWeek(new Date()));
            wrapper.eq("type",Constant.DAILY)
                    .eq("area",Constant.city)
                    .orderByAsc("ct")
                    .apply(
                            //**天内的数据
                            "ct >= " + "'"+ssm.format(DateUtil.beginOfWeek(pastDate))+"'")
                    .apply(
                            "ct <= " + "'"+ssm.format(DateUtil.endOfWeek(pastDate))+"'");
        }
        else {
            wrapper.eq("type",Constant.DAILY)
                    .eq("area",Constant.city)
                    .orderByAsc("ct")
                    .apply(
                            //**天内的数据
                            "ct >= " + "'"+ssm.format(DateUtils.getPastDate(days,date))+"'")
                    .apply(
                            "ct <= " + "'"+ssm.format(date)+"'");
        }
        return  pollutantAvgMapper.selectList(wrapper);
    }


    @Override
    public Set<PollutantAvg> selectAVGByType(Integer type) {
        String limit = "limit 1";
        if (type == Constant.DAILY) limit = "limit 30";
        else if (type == Constant.WEEKLY) limit = "limit 20";
        else if (type == Constant.MONTHLY) limit = "limit 12";
        else if (type == Constant.YEARLY) limit = "limit 3";
        LambdaQueryWrapper<PollutantAvg> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PollutantAvg::getArea,Constant.city)
                .eq(PollutantAvg::getType,type)
                .groupBy(PollutantAvg::getId,PollutantAvg::getAqi,PollutantAvg::getArea,PollutantAvg::getCo,PollutantAvg::getNo2,
                        PollutantAvg::getO3,PollutantAvg::getPm10,PollutantAvg::getPm25,PollutantAvg::getType,PollutantAvg::getSo2,
                        PollutantAvg::getCt)
                .orderByDesc(PollutantAvg::getCt).last(limit);
        TreeSet<PollutantAvg> set = new TreeSet<>();
        set.addAll(pollutantAvgMapper.selectList(wrapper));
        return set;
    }

    @Override
    public List<PollutantAvg> selectAllByDay() {

        LambdaQueryWrapper<PollutantAvg> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PollutantAvg::getType,Constant.DAILY)
                .eq(PollutantAvg::getArea,Constant.city)
//                .orderByAsc(PollutantAvg::getCt)
                .groupBy(PollutantAvg::getId,PollutantAvg::getAqi,PollutantAvg::getArea,PollutantAvg::getCo,PollutantAvg::getNo2,
                        PollutantAvg::getO3,PollutantAvg::getPm10,PollutantAvg::getPm25,PollutantAvg::getType,PollutantAvg::getSo2,
                        PollutantAvg::getCt);

        return pollutantAvgMapper.selectList(wrapper);
    }

    @Override
    public TreeMap<String, HashMap<Integer, Integer>> daysOfQualities(Boolean yearData) {
        /**
         * <月份，<类型,天数>>
         */
        TreeMap<String,HashMap<Integer,Integer>> res = new TreeMap<>();
        Integer[][] rank = {{0,50},{50,100},{100,150},{150,200},{200,300},{300,500}};
        Integer[] types ={Constant.EXCELLENT,Constant.GOOD,Constant.MILD,Constant.MODERATE,Constant.SEVERE,Constant.WORSTEST};
        if (yearData){
            for (int i = 0; i < rank.length; i++) {
                //统计全年各等级天数
                List<PollutantMonthVo> year = pollutantAvgMapper.selectDaysOfQuantityYear(
                        new QueryWrapper<PollutantAvg>()
                                .eq("type", 1)
                                .eq("area", Constant.city)
                                .apply("aqi >"+rank[i][0]+" and aqi<="+rank[i][1]));

                int finalI = i;
                if (year.size()!=0){
                    year.forEach(data->{
                        if (ObjectUtil.isEmpty(res.get(data.getDate()))){
                            HashMap<Integer,Integer> map = new HashMap<>();
                            map.put(types[finalI],data.getTotal());
                            res.put(data.getDate(),map);
                        }else {
                            HashMap<Integer, Integer> map = res.get(data.getDate());
                            map.put(types[finalI],data.getTotal());
                            res.put(data.getDate(),map);
//                            System.out.println(map);
                        }

                    });

                }

            }
        }else {
            for (int i = 0; i < rank.length; i++) {
                List<PollutantMonthVo> excellent = pollutantAvgMapper.selectDaysOfQuantity(
                        new QueryWrapper<PollutantAvg>()
                                .eq("type", 1)
                                .eq("area", Constant.city)
                                .apply("aqi >"+rank[i][0]+" and aqi<="+rank[i][1]));
                int finalI = i;
                if (excellent.size()!=0) {
                    excellent.forEach(data->{
                        if (ObjectUtil.isEmpty(res.get(data.getDate()))){
                            HashMap<Integer,Integer> map = new HashMap<>();
                            map.put(types[finalI],data.getTotal());
                            res.put(data.getDate(),map);
//                            System.out.println(map);
                        }else {
                            HashMap<Integer, Integer> map = res.get(data.getDate());
                            map.put(types[finalI],data.getTotal());
                            res.put(data.getDate(),map);
//                            System.out.println(map);
                        }
                    });
                }

            }
        }
        return res;
    }

    /**
     * 查询均值查询
     *
     * @param id 均值查询主键
     * @return 均值查询
     */
    @Override
    public PollutantAvg selectPollutantAvgById(Long id)
    {
        return pollutantAvgMapper.selectPollutantAvgById(id);
    }

    /**
     * 查询均值查询列表
     *
     * @param pollutantAvg 均值查询
     * @return 均值查询
     */
    @Override
    public List<PollutantAvg> selectPollutantAvgList(PollutantAvg pollutantAvg)
    {
        return pollutantAvgMapper.selectPollutantAvgList(pollutantAvg);
    }

    /**
     * 新增均值查询
     *
     * @param pollutantAvg 均值查询
     * @return 结果
     */
    @Override
    public int insertPollutantAvg(PollutantAvg pollutantAvg)
    {
        return pollutantAvgMapper.insertPollutantAvg(pollutantAvg);
    }

    /**
     * 修改均值查询
     *
     * @param pollutantAvg 均值查询
     * @return 结果
     */
    @Override
    public int updatePollutantAvg(PollutantAvg pollutantAvg)
    {
        return pollutantAvgMapper.updatePollutantAvg(pollutantAvg);
    }

    /**
     * 批量删除均值查询
     *
     * @param ids 需要删除的均值查询主键
     * @return 结果
     */
    @Override
    public int deletePollutantAvgByIds(Long[] ids)
    {
        return pollutantAvgMapper.deletePollutantAvgByIds(ids);
    }

    /**
     * 删除均值查询信息
     *
     * @param id 均值查询主键
     * @return 结果
     */
    @Override
    public int deletePollutantAvgById(Long id)
    {
        return pollutantAvgMapper.deletePollutantAvgById(id);
    }
}
